package com.swak.reactivex.threads;

import java.util.concurrent.Executor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.swak.metrics.MetricsFactory;
import com.swak.metrics.PoolMetrics;

/**
 * The execution context of a ThreadPool execution.
 *
 * @author: lifeng
 * @date: 2020/3/29 12:17
 */
public interface Context extends Executor {

	Logger log = LoggerFactory.getLogger(Context.class);

	/**
	 * 执行任务
	 *
	 * @param command 任务
	 */
	void execute(Runnable command);

	/**
	 * 获得指标统计工具
	 * 
	 * @return
	 */
	PoolMetrics<Object> getMetrics();

	/**
	 * 线程执行的包装
	 *
	 * @param command 任务
	 * @return 是否有异常
	 */
	default boolean executeTask(Runnable command) {
		Thread th = Thread.currentThread();
		if (!(th instanceof SwakThread)) {
			throw new IllegalStateException("Uh oh! context executing with wrong thread! " + th);
		}
		SwakThread current = (SwakThread) th;
		current.executeStart();
		try {
			current.setContext(this);
			command.run();
			return true;
		} catch (Throwable t) {
			log.error("Caught unexpected Throwable", t);
			return false;
		} finally {
			current.executeEnd();
		}
	}

	/**
	 * 设置监控工具
	 *
	 * @param metricsFactory 监控工具
	 */
	default void applyMetrics(MetricsFactory metricsFactory) {
	}

	/**
	 * 在Context 中继续执行
	 * 
	 * @param command
	 */
	default void runOnContext(Runnable command) {
		Thread currentThread = Thread.currentThread();
		if (currentThread instanceof SwakThread) {
			Context context = ((SwakThread) currentThread).getContext();
			if (context == this) {
				command.run();
				return;
			}
		}
		this.execute(command);
	}
}